package com.ts.opengl.simpleDraw

import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.opengl.GLES20.GL_LINEAR
import android.opengl.GLES20.GL_LINEAR_MIPMAP_LINEAR
import android.opengl.GLES20.GL_NEAREST
import android.opengl.GLES20.GL_NONE
import android.opengl.GLES20.GL_TEXTURE_2D
import android.opengl.GLES20.GL_TEXTURE_MAG_FILTER
import android.opengl.GLES20.GL_TEXTURE_MIN_FILTER
import android.opengl.GLES20.GL_UNSIGNED_INT
import android.opengl.GLES20.GL_UNSIGNED_SHORT
import android.opengl.GLES20.glBindTexture
import android.opengl.GLES20.glGenerateMipmap
import android.opengl.GLES20.glGetError
import android.opengl.GLES20.glTexParameteri
import android.opengl.GLES30
import android.opengl.GLSurfaceView
import android.opengl.GLUtils
import android.util.Log
import com.ts.audiocamera.R
import java.nio.FloatBuffer
import java.nio.IntBuffer
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10

abstract class BaseRender(var conext:Context):GLSurfaceView.Renderer {
//    var fboTexture= intArrayOf(1)
//
//    var fbo=IntArray(1)

    val frameBuffers = IntArray(1)
    val textures = IntArray(1)
    var vertex= floatArrayOf(
        // positions         //color              // texture coords
        -1.0f,  -1.0f, 0.0f,   1.0f, 0.0f, 0.0f,    1.0f, 1.0f, // top right
        1.0f, -1.0f, 0.0f,   1.0f, 0.0f, 1.0f,   0.0f, 1.0f, // bottom right
        -1.0f, 1.0f, 0.0f,   1.0f, 0.0f, 1.0f,   1.0f,0.0f, // bottom left
        1.0f,  1.0f, 0.0f,   0.0f, 0.5f, 1.0f,   0.0f, 0.0f, // top left
    )


    var vertexffbo= floatArrayOf(
        // positions         //color              // texture coords
        -1.0f,  -1.0f, 0.0f,   1.0f, 0.0f, 0.0f,    1.0f, 0.0f, // top right
        1.0f, -1.0f, 0.0f,   1.0f, 0.0f, 1.0f,   0.0f, 0.0f, // bottom right
        -1.0f, 1.0f, 0.0f,   1.0f, 0.0f, 1.0f,   1.0f,1.0f, // bottom left
        1.0f,  1.0f, 0.0f,   0.0f, 0.5f, 1.0f,   0.0f, 1.0f, // top left
    )

    var element= intArrayOf(
        0, 1, 2,
        1, 2, 3

    )

    var program=0;


     val vertexFloat: FloatBuffer by lazy {
         openglUtil.createFloatBuffer(vertex)
     }



    val vertexFloatFbo: FloatBuffer by lazy {
        openglUtil.createFloatBuffer(vertexffbo)
    }
    val elementInt: IntBuffer by lazy {
        openglUtil.createIntBuffer(element)
    }
    var vao=IntArray(2)
    var vbo=IntArray(2)
    var ebo=IntArray(2)

    var imagetextture=IntArray(1)
    abstract fun getFragmentId():Int
    abstract fun getVertex():Int
    override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
        program=openglUtil.createProgram(conext,getVertex(),getFragmentId());
        initBuffer()
        createTexture();
    }


    var bitmap:Bitmap?=null
    fun createTexture(){
        GLES30.glGenTextures(imagetextture.size,imagetextture,0)
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D,imagetextture[0])
        bitmap=BitmapFactory.decodeResource(conext.resources, R.drawable.cdemo)
        //设置纹理过滤参数，GL_TEXTURE_MIN_FILTER代表纹理缩写的情况，GL_LINEAR_MIPMAP_LINEAR代表缩小时使用三线性过滤的方式，至于过滤方式以后再详解
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
        //GL_TEXTURE_MAG_FILTER代表纹理放大，GL_LINEAR代表双线性过滤
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
        //加载实际纹理图像数据到OpenGL ES的纹理对象中，这个函数是Android封装好的，可以直接加载bitmap格式，
        GLUtils.texImage2D(GL_TEXTURE_2D, 0, bitmap, 0)
        //bitmap已经被加载到OpenGL了，所以bitmap可释放掉了，防止内存泄露

//        GLES30.glTexImage2D(GLES30.GL_TEXTURE_2D,0,GLES30.GL_RGB,
//            width, height,0,GLES30.GL_RGB,
//            GLES30.GL_UNSIGNED_SHORT_5_6_5,)
        bitmap?.recycle()
        //我们为纹理生成MIP贴图，提高渲染性能，但是可占用较多的内存
        glGenerateMipmap(GL_TEXTURE_2D)
        //现在OpenGL已经完成了纹理的加载，不需要再绑定此纹理了，后面使用此纹理时通过纹理对象的ID即可
        glBindTexture(GL_TEXTURE_2D, 0)

    }

    fun initBuffer(){

        GLES30.glGenVertexArrays(vao.size,vao,0)
        GLES30.glGenBuffers(vbo.size,vbo,0)

        GLES30.glBindVertexArray(vao[0])
        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER,vbo[0])
        GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER,vertexFloat.capacity()*4,vertexFloat,GLES30.GL_STATIC_DRAW);

        vertexFloat.position(0);
        GLES30.glVertexAttribPointer(0,3,GLES30.GL_FLOAT,false,8*4,0)
        GLES30.glEnableVertexAttribArray(0)

        vertexFloat.position(3);
        GLES30.glVertexAttribPointer(1,3,GLES30.GL_FLOAT,false,8*4,3*4)
        GLES30.glEnableVertexAttribArray(1)

        vertexFloat.position(6);
        GLES30.glVertexAttribPointer(2,2,GLES30.GL_FLOAT,false,8*4,6*4)
        GLES30.glEnableVertexAttribArray(2)

        GLES30.glGenBuffers(ebo.size,ebo,0)
        GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER,ebo[0])
        GLES30.glBufferData(GLES30.GL_ELEMENT_ARRAY_BUFFER,elementInt.capacity()*4,elementInt,GLES30.GL_STATIC_DRAW);



        GLES30.glBindVertexArray(0)
        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER,0)
        GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER,0)

        GLES30.glBindVertexArray(vao[1])
        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER,vbo[1])
        GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER,vertexFloatFbo.capacity()*4,vertexFloatFbo,GLES30.GL_STATIC_DRAW);

        vertexFloat.position(0);
        GLES30.glVertexAttribPointer(0,3,GLES30.GL_FLOAT,false,8*4,0)
        GLES30.glEnableVertexAttribArray(0)

        vertexFloat.position(3);
        GLES30.glVertexAttribPointer(1,3,GLES30.GL_FLOAT,false,8*4,3*4)
        GLES30.glEnableVertexAttribArray(1)

        vertexFloat.position(6);
        GLES30.glVertexAttribPointer(2,2,GLES30.GL_FLOAT,false,8*4,6*4)
        GLES30.glEnableVertexAttribArray(2)

        GLES30.glGenBuffers(ebo.size,ebo,0)
        GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER,ebo[1])
        GLES30.glBufferData(GLES30.GL_ELEMENT_ARRAY_BUFFER,elementInt.capacity()*4,elementInt,GLES30.GL_STATIC_DRAW);

        GLES30.glBindVertexArray(0)
        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER,0)
        GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER,0)
        initBufferNew();


    }


    protected open fun initBufferNew(){

    }


    private  val TAG = "BaseRender"
    override fun onDrawFrame(gl: GL10?) {

        GLES30.glUseProgram(program)


        GLES30.glBindVertexArray(vao[0])
//        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D,textures[0])
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D,imagetextture[0])
        Log.e(TAG,glGetError().toString()+"")
        GLES30.glDrawElements(GLES30.GL_TRIANGLE_STRIP,6, GL_UNSIGNED_INT,0)

        GLES30.glBindVertexArray(GL_NONE)
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D,GL_NONE)
    }

    var width=0;
    var height=0;
    override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {

        this.width=width;
        this.height=height;
        GLES30.glViewport(0,0,width,height)
    }
}